package com.yl.shiro;

import com.yl.core.UserService;
import com.yl.model.User;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import java.util.Arrays;

/**
 * 功能或描述：授权realm，认证时信息获取从此处获取
 * 但认证缓存等认证操作在AuthenticationRealm中完成
 *
 * @author DR.YangLong
 *         date 14-10-28
 *         time 上午11:07
 *         email 410357434@163.com
 * @version 1.0
 * @see org.apache.shiro.realm.AuthenticatingRealm
 * 授权信息获取在此处完成
 * @see org.apache.shiro.realm.AuthorizingRealm
 * 他们为继承的结构parent AuthenticatingRealm << child AuthorizingRealm
 * <p/>
 * package com.yl.shiro
 * @since 1.0
 * module 修正:            日期：
 */
public class CustomRealm extends AuthorizingRealm {
    /**
     * shiro业务支撑类，包括用户的查询，用户权限，角色的查询
     */
    private UserService userService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //获取当前用户
        User user=ShiroUtil.getUserByPrincipalsRealmName(principals,getName());
        //创建授权信息实体
        SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();
        //获取用户角色并添加到授权信息实体
        String[] roles={"admin","custom","user"};//换成数据库直接查询list
        authorizationInfo.addRoles(Arrays.asList(roles));
        //获取用户权限并添加到授权信息实体
        String[] permissions={"create","delete","update"};
        authorizationInfo.addStringPermissions(Arrays.asList(permissions));
        //此处处理完成可以放入一些额外的通用信息到session中
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken passwordToken=(UsernamePasswordToken)token;
        User user=new User();
        user.setAccount(passwordToken.getUsername());
        user.setPwd(new String(passwordToken.getPassword()));
        user=userService.login(user);
        //一些前置处理，判断帐号是否存在，帐号是否锁定
        if(user==null){
            throw new UnknownAccountException();//没找到帐号;
        }
       SimpleAuthenticationInfo authenticationInfo=
               new SimpleAuthenticationInfo(user,user.getPwd(),getName());
        return authenticationInfo;
    }

    /**
     * 获取认证信息在缓存中的键值
     * 此方法可以自定义认证信息在缓存中的键值，可以使用唯一标识和信息对应的方式
     * 此处的principals为此类中doGetAuthenticationInfo方法设置的principal，
     * 如果此realm前面还有realm，将有多个principal
     *
     * @param principals 凭证
     * @return key
     */
    protected Object getAuthorizationCacheKey(PrincipalCollection principals) {
        return super.getAuthorizationCacheKey(principals);
    }

    /**
     * 此方法登录时不会调用，且使用缓存时才调用此方法，默认使用传入的token键值作为缓存key，
     * 此方法在登出时调用，返回值必须和
     * {@link #getAuthenticationCacheKey(org.apache.shiro.authc.AuthenticationToken)}相同
     * <p/>
     * {@link org.apache.shiro.realm.AuthenticatingRealm#getAuthenticationCacheKey(org.apache.shiro.subject.PrincipalCollection)}
     *
     * @param principals
     * @return
     */
    @Override
    protected Object getAuthenticationCacheKey(PrincipalCollection principals) {
        return super.getAuthenticationCacheKey(principals);
    }

    /**
     * 认证缓存key，登录时调用，默认使用token值，使用缓存时才调用此方法
     * {@link org.apache.shiro.realm.AuthenticatingRealm#getAuthenticationCacheKey(org.apache.shiro.authc.AuthenticationToken)}
     *
     * @param token token
     * @return key
     */
    protected Object getAuthenticationCacheKey(AuthenticationToken token) {
        return super.getAuthenticationCacheKey(token);
    }

    public UserService getUserService() {
        return userService;
    }

    public void setUserService(UserService userService) {
        this.userService = userService;
    }
}
